/*
 * 
 *
 * Authors: Soeren Gebbert, soeren.gebbert@vti.bund.de
 *          Axel Don, axel.don@vti.bund.de
 *
 * Copyright:
 *
 * Johann Heinrich von Thünen-Institut
 * Institut für Agrarrelevante Klimaforschung
 *
 * Phone: +49 (0)531 596 2601
 *
 * Fax:+49 (0)531 596 2699
 *
 * Mail: ak@vti.bund.de
 *
 * Bundesallee 50
 * 38116 Braunschweig
 * Germany
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include "carb_particle.h"

/* -------------------------------------------------------------------------- */
carb_particle::carb_particle() : particle_base() {
    this->x = 0;
    this->y = 0;
    this->z = 0;
    this->is_doc = false;
    this->mass = 0;
    this->age = 1;
    this->active = true;
    this->init_params = NULL;
    this->run_params = NULL;
}
/* -------------------------------------------------------------------------- */
carb_particle::carb_particle(initial_parameters *init_params,
        runtime_parameters *run_params) : particle_base(init_params, run_params) {
    this->x = (float) drand48() * init_params->width;
    this->y = (float) drand48() * init_params->height;
    this->z = (float) drand48() * init_params->max_carb_depth;
    
    /* Use the carbon flow fraction to specify if the carbon particle is dissolved */
    if(drand48()*100 <= run_params->doc_fraction) {
        this->is_doc = true;
    } else {
        this->is_doc = false;
    }
    
    this->mass = run_params->total_carb_input_mass / (float)run_params->new_carb_particles;
    this->age = 1;
    this->active = true;
    this->init_params = init_params;
    this->run_params = run_params;
}
/* -------------------------------------------------------------------------- */
carb_particle::carb_particle(float x, float y, float z, float mass, int age, bool is_doc,  initial_parameters *init_params,
        runtime_parameters *run_params) : particle_base(init_params, run_params) {
    this->x = x;
    this->y = y;
    this->z = z;
    this->is_doc = is_doc;
    this->mass = mass;
    this->age = age;
    this->active = true;
    this->init_params = init_params;
    this->run_params = run_params;
}
/* -------------------------------------------------------------------------- */
void carb_particle::aging() {
    this->age++;
}
/* -------------------------------------------------------------------------- */
void carb_particle::move() {

    float width = this->init_params->width;
    float height = this->init_params->height;
    float depth = this->init_params->depth;
    float dx = this->run_params->dxmicr;
    float dy = this->run_params->dymicr;
    float dz = this->run_params->dzmicr;
    float dg = this->run_params->carbon_flow;

    float x = (float) (drand48() - 0.5) * dx;
    float y = (float) (drand48() - 0.5) * dy;
    float z = (float) (drand48() - 0.5) * dz;
    
    /* The gravitational dominated velocity will be added as
     * vector component in the z direction. Gravitation is only effective
     * in negetaive z direction.
     */
    this->x += x;
    this->y += y;
    this->z += z;
    
    /* Gravity works only on DOC particles */
    if(this->is_doc) {
        float g = (float) (drand48() * fabs(dg));
        this->z -= g;
    }
    
    //cout << "Move carbon about dx: " << x << " dz: " << z << endl;
    /* Boundary conditions */
    if (this->x < 0.0)
        this->x += width; /*swap to other side */
    if (this->x > width)
        this->x -= width; /*swap to other side */
    if (this->y < 0.0)
        this->y += height; /*swap to other side */
    if (this->y > height)
        this->y -= height; /*swap to other side */
    if (this->z > 0.0)
        this->z = -1.0 * this->z; /* Reflect */
    if (this->z < depth)
        this->active = false;
}
/* -------------------------------------------------------------------------- */
float carb_particle::get_eaten() {
    /* In case it was already eaten, return 0.0 */
    if(this->active == false)
        return 0.0;
    /* the carbon got eaten */
    this->active = false;
    return this->mass;
}